/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package flower;

import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.Timer;

/**
 * It's the ultimate flower pictures clicking game. The normal difficulties are easy, but try the SECRET 7,8,9 and face the true challenge!
 * @author Yan Couto
 * @version 0.6
 */
public class FlowerMain implements ActionListener{
    
    static final FlowerMain INSTANCE = new FlowerMain();
    static final List<Flower> flowers;
    static final List<FlowerImage> flowerImages;
    static final Image background;
    static final int WIDTH = 900, HEIGHT = 670;
    static final Rectangle2D frameBounds;
    static final Random random = new Random();
    static final JFrame frame = new JFrame();
    static final PaintArea paint = new PaintArea();
    static final Timer paintTimer = new Timer(40, INSTANCE),countdown = new Timer(1,INSTANCE);
    private static Toolkit kit = Toolkit.getDefaultToolkit();
    private static int count,difficulty = -1, countTime;
    private static long time;
    

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        frame.add(paint);
        frame.setSize(WIDTH+17, HEIGHT+39);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        
        countdown.setActionCommand("countdown");
        countdown.setRepeats(true);
        countdown.setDelay(1);
        
        createLevel(getNum("Qual o nível da tela? (0-6)"));
        
        paintTimer.setRepeats(true);
        paintTimer.setActionCommand("paint");
        paintTimer.start();
    }
    
    public static int getNum(String text) {
        while(true) {
        String s = JOptionPane.showInputDialog(frame, text, "4");
        if(s==null) System.exit(0);
            try {
                int x = Integer.parseInt(s);
                if(x<0 || x>9) continue;
                return x;
            } catch (NumberFormatException numberFormatException) {}
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getActionCommand().equals("paint")) {
            paint.repaint();
            kit.sync();
        } else if(e.getActionCommand().equals("countdown")) {
            count = (int) (countTime - (System.currentTimeMillis()-time));
            if(count <= 0) {
                count = 0;
                levelEnded(false);
            }
        }
    }
    
    static void createLevel(int difficulty) {
        paintTimer.stop();
        FlowerMain.difficulty = difficulty;
        int numberOfImages = difficulty*3+3;
        count = (int) ( difficulty + 2)*1000;
        if(difficulty==7) count = 5*1000;
        if(difficulty==8) { numberOfImages = 24; count = 4*1000; }
        if(difficulty==9) { numberOfImages = 24; count = 3*1000; }
        countTime = count;
        
        flowerImages.clear();
        for(int i=0;i<numberOfImages;i++) {
            int ind = random.nextInt(flowers.size());
            try {
                flowerImages.add(new FlowerImage(flowers.get(ind)));
            } catch (Exception ex) {
                System.err.println("image not added");
                continue;
            }
        }
        time = System.currentTimeMillis();
        countdown.restart();
        paintTimer.restart();
    }
    
    static void levelEnded(boolean succeded) {
        countdown.stop();
        System.err.println("It took " + (System.currentTimeMillis() - time) + "ms");
        String ask = "Qual o nível da tela? (0-6)";
        if(succeded) ask = "Parabéns, você passou. " + ask;
        else ask = "Você não conseguiu colorir a tempo... " + ask;
        createLevel(getNum(ask));
    }
    
    
    private static class PaintArea extends Component implements MouseListener{
        
        public PaintArea() { 
            this.addMouseListener(this); 
            this.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
        }

        @Override
        public void paint(Graphics g) {
            super.paint(g);
            Graphics2D g2 = (Graphics2D) g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            
            g2.drawImage(background, 0, 0, frame);
            
            g2.setColor(Color.BLACK);
            
            g2.drawString("Colorful Flowers", 10, 20);
            g2.drawString((float)count/1000 + "s", 100, 35);
            if(difficulty!=-1) g2.drawString("Difficulty   " + difficulty, 47, 47);
            for(FlowerImage flower : flowerImages) {
                g2.drawImage(flower.image, flower.location.x, flower.location.y, frame);
            }
//            //TEST
//            int y = -100;
//            for(Flower flower : flowers)
//                g2.drawImage(flower.normal,0,y+=100,frame);
//            //ENDTEST
            
            g2.dispose();
        }

        @Override
        public void mouseClicked(MouseEvent e) {}

        @Override
        public void mousePressed(MouseEvent e) {
            boolean complete = true;
            for(FlowerImage fi : flowerImages){
                if(fi.hasPoint(e.getPoint()))
                    fi.normalize();
                if(complete && !fi.normalized()) complete = false;
            }
            
            if(complete) {
                levelEnded(true);
            }
        }

        @Override
        public void mouseReleased(MouseEvent e) {}

        @Override
        public void mouseEntered(MouseEvent e) {}

        @Override
        public void mouseExited(MouseEvent e) {}
    }
    
    static class FlowerImage {
        Image image;
        Point location;
        Rectangle2D bounds;
        Flower flower;
        
        public FlowerImage(Flower f) throws Exception {
            location = randomPoint();
            flower = f;
            image = f.gray;
            int safe; int max = 1000000;
            for(safe = 0; safe < max && !isClear();safe++)
               location = randomPoint();
            if(safe == max) throw new Exception("couldn't find point"); 
        }
        
        public boolean hasPoint(Point p) { return bounds.contains(p); }
        public void normalize() { image = flower.normal; }
        public boolean normalized() { return image == flower.normal; }
        public boolean isClear() {
            boolean clear =  frameBounds.contains(bounds = new Rectangle2D.Float(location.x, location.y, image.getWidth(frame), 100));
            if(!clear) return false;
            for(FlowerImage fi: flowerImages){
                if(fi.bounds.intersects(bounds)) return false;
            }
            return true;
        }
    }
    
    private static Point randomPoint() {
        int x = random.nextInt(WIDTH);
        int y = random.nextInt(HEIGHT);
        if(x<125 && y <32) return new Point(50,50);
        return new Point(x,y);
    }
    
    static {
        background = kit.getImage(FlowerMain.class.getResource("background.jpg"));
        flowers =  new ArrayList<Flower>();
        flowerImages = new ArrayList<FlowerImage>();
        frameBounds = new Rectangle.Float(0, 0, WIDTH, HEIGHT);
        Flower f;
        for(int i = 1; i<=6 && (f = Flower.newFlower(i))!=null ; i++) {
            flowers.add(f);
        }
        System.err.println(flowers);
    }
}
